package com.linkmed.storage.utils;

import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Value;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Component
public class StorageFileUtil {

    @Value("${storage.oss.bucketName}")
    private  String bucketName;
    @Value("${storage.oss.pageNum}")
    private  Integer pageNum;

    private static Logger logger = LoggerFactory.getLogger(StorageFileUtil.class);

    private  Integer deleteCount =0;

    ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 200, TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<>(200) );

     public  List<String> listHosipital(String prefix){
        List<String> list = new ArrayList<>();
        ObsClient obsClient = ObsClientFactory.getObsClient();
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        request.setMaxKeys(200);
        logger.info("需要打开的文件夹路径{}",prefix);
        if(!prefix.equals("/")){
            String str = prefix.substring(1,prefix.length());
            request.setPrefix(str+"/");
            // 设置文件夹分隔符"/"
            request.setDelimiter("/");
        }else{
            // 设置文件夹分隔符"/"
            request.setDelimiter("/");
        }

        //request.setPrefix("/05");
        ObjectListing result;
       // do {
            result = obsClient.listObjects(request);
         for(ObsObject obsObject : result.getObjects())
         {
             if(("/"+obsObject.getObjectKey()).equals(prefix+"/")){
                 continue;
             }
             list.add(obsObject.getObjectKey());
             // System.out.println("\t" + obsObject.getOwner());
         }
            List<String> hosipitalIdList =  result.getCommonPrefixes();
            String marker = result.getNextMarker();
            request.setMarker(marker);
            System.out.println("marker = " + marker);
            for (String str : hosipitalIdList){
                list.add(str);
            }
     //   }while (result.isTruncated());

         return list;

    }

    public  List<String> listChild(String parentId){
        List<String> list = new ArrayList<>();
        ObsClient obsClient = ObsClientFactory.getObsClient();
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        request.setMaxKeys(200);
        request.setPrefix(parentId);
        // 设置文件夹分隔符"/"
        request.setDelimiter("/");
        //request.setPrefix("/05");
        ObjectListing result;
        //do {
            result = obsClient.listObjects(request);
            List<String> hosipitalIdList =  result.getCommonPrefixes();
            String marker = result.getNextMarker();
            request.setMarker(marker);
            System.out.println("marker = " + marker);
            for (String str : hosipitalIdList){
                list.add(str);
            }
      //  }while (result.isTruncated());
        return list;

    }

    public  boolean deleteObject(String objectKey){
        try {
            logger.info("开始删除对象{}",objectKey);
            ObsClient obsClient = ObsClientFactory.getObsClient();
            DeleteObjectResult objectResult =  obsClient.deleteObject(bucketName,objectKey);
            if(null != objectResult){
                if(objectResult.getStatusCode()>200 && objectResult.getStatusCode()<300){
                    return true;
                }
            }
        } catch (ObsException e) {
            e.printStackTrace();
            logger.error("删除对象异常",e);
        }
        return false;
    }

    public  boolean deleteFolder(String folderUrl){

        long startTime = System.currentTimeMillis();
        long endTime = 0L;
        try {
            logger.info("删除文件夹{}开始，开始时间{}",folderUrl,startTime);
            deleteCount =0;
            //验证文件夹格式
            String folderHead = folderUrl.substring(0,1);
            String folderTail = folderUrl.substring(folderUrl.length()-1,folderUrl.length());
            if(!folderHead.equals("/") && folderTail.equals("/")){
                logger.info("验证文件夹路径格式通过");

                ObsClient obsClient = ObsClientFactory.getObsClient();
                deletelistObjectsByPrefix(obsClient,folderUrl);
            }
             endTime = System.currentTimeMillis();
            logger.info("删除文件夹共耗时{}毫秒",endTime-startTime);
            logger.info("本次共删除{}个文件",deleteCount);
        } catch (Exception e) {
            logger.info("删除文件夹共耗时{}毫秒",endTime-startTime);
            logger.info("本次共删除{}个文件",deleteCount);
            logger.error("删除文件夹异常",e);
            return false;
        }
        return true;
    }


    public  boolean deleteExamFolder(String folderUrl){

        long startTime = System.currentTimeMillis();
        long endTime = 0L;
        try {
            logger.info("删除文件夹{}开始，开始时间{}",folderUrl,startTime);
            deleteCount =0;
            //验证文件夹格式
            String folderHead = folderUrl.substring(0,1);
            String folderTail = folderUrl.substring(folderUrl.length()-1,folderUrl.length());
            if(!folderHead.equals("/") && folderTail.equals("/")){
                logger.info("验证文件夹路径格式通过");
                ObsClient obsClient = ObsClientFactory.getObsClient();
                ListObjectsRequest request = new ListObjectsRequest(bucketName);
                request.setMaxKeys(pageNum);
                request.setPrefix(folderUrl);
                request.setDelimiter("/");
                ObjectListing result = null;

                DeleteObjectsResult deleteResult = null;
                DeleteObjectsRequest delteRequest = new DeleteObjectsRequest(bucketName);
                do {
                    logger.info("正在遍历{}文件夹下的文件",folderUrl);
                    List<KeyAndVersion> toDelete = new ArrayList<KeyAndVersion>();
                    result = obsClient.listObjects(request);
                    for(ObsObject obsObject : result.getObjects())
                    {
                        deleteCount++;
                        toDelete.add(new KeyAndVersion(obsObject.getObjectKey()));
                        logger.info("添加删除的文件{}",obsObject.getObjectKey());
                    }
                    if(toDelete.size()>0){
                        delteRequest.setKeyAndVersions(toDelete.toArray(new KeyAndVersion[toDelete.size()]));
                        deleteResult = obsClient.deleteObjects(delteRequest);
                        // logger.info("删除文件返回结果{}",deleteResult.getDeletedObjectResults());
                        if(deleteResult.getErrorResults().size()>0){
                            logger.info("删除文件出现异常文件{}",deleteResult.getErrorResults());
                        }

                    }
                   Semaphore semaphore = new Semaphore(10);
                    for(String str : result.getCommonPrefixes())
                    {
                        semaphore.acquire();
                        long startTimeFo = System.currentTimeMillis();
                        logger.info("删除{}文件夹开始{}",str,startTimeFo);
                        DeleteFolderTask deleteFolderTask = new DeleteFolderTask(obsClient,str,bucketName,pageNum,semaphore);
                        executor.submit(deleteFolderTask);
                       // deletelistObjectsByFolder(obsClient,str);
                        // deletelistObjectsByPrefix(obsClient,str);
                        long endTimeFo = System.currentTimeMillis();
                        logger.info("删除{}文件夹结束,耗时{}毫秒",str,endTimeFo-startTimeFo);
                    }

                }while (result.isTruncated());
               // executor.shutdown();

            }


            endTime = System.currentTimeMillis();
            logger.info("删除文件夹共耗时{}毫秒",endTime-startTime);
            logger.info("本次共删除{}个文件",deleteCount);
        } catch (Exception e) {
            logger.info("删除文件夹共耗时{}毫秒",endTime-startTime);
            logger.info("本次共删除{}个文件",deleteCount);
            logger.error("删除文件夹异常",e);
            return false;
        }
        return true;
    }

    void deletelistObjectsByFolder(ObsClient obsClient,String prefix) throws
            Exception
    {
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        request.setMaxKeys(pageNum);
        request.setPrefix(prefix);

        ObjectListing result = null;

        DeleteObjectsResult deleteResult = null;
        DeleteObjectsRequest delteRequest = new DeleteObjectsRequest(bucketName);
        do {
            logger.info("正在遍历{}文件夹下的文件",prefix);
            List<KeyAndVersion> toDelete = new ArrayList<KeyAndVersion>();
            result = obsClient.listObjects(request);
            for(ObsObject obsObject : result.getObjects())
            {
                deleteCount++;
                toDelete.add(new KeyAndVersion(obsObject.getObjectKey()));
                logger.info("添加删除的文件{}",obsObject.getObjectKey());
            }
            if(toDelete.size()>0){
                delteRequest.setKeyAndVersions(toDelete.toArray(new KeyAndVersion[toDelete.size()]));
                deleteResult = obsClient.deleteObjects(delteRequest);
                // logger.info("删除文件返回结果{}",deleteResult.getDeletedObjectResults());
                if(deleteResult.getErrorResults().size()>0){
                    logger.info("删除文件出现异常文件{}",deleteResult.getErrorResults());
                }

            }
            /*for(String str : result.getCommonPrefixes())
            {
                deletelistObjectsByPrefix(obsClient,str);
            }*/

        }while (result.isTruncated());

    }

     void deletelistObjectsByPrefix(ObsClient obsClient,String prefix) throws
            Exception
    {
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        request.setMaxKeys(pageNum);
        request.setPrefix(prefix);
        request.setDelimiter("/");
        ObjectListing result = null;

        DeleteObjectsResult deleteResult = null;
        DeleteObjectsRequest delteRequest = new DeleteObjectsRequest(bucketName);
        do {
            logger.info("正在遍历{}文件夹下的文件",prefix);
            List<KeyAndVersion> toDelete = new ArrayList<KeyAndVersion>();
            result = obsClient.listObjects(request);
            for(ObsObject obsObject : result.getObjects())
            {
                deleteCount++;
                toDelete.add(new KeyAndVersion(obsObject.getObjectKey()));
                logger.info("添加删除的文件{}",obsObject.getObjectKey());
            }
            if(toDelete.size()>0){
                delteRequest.setKeyAndVersions(toDelete.toArray(new KeyAndVersion[toDelete.size()]));
                deleteResult = obsClient.deleteObjects(delteRequest);
               // logger.info("删除文件返回结果{}",deleteResult.getDeletedObjectResults());
                if(deleteResult.getErrorResults().size()>0){
                    logger.info("删除文件出现异常文件{}",deleteResult.getErrorResults());
                }

            }
            for(String str : result.getCommonPrefixes())
            {
                deletelistObjectsByPrefix(obsClient,str);
            }

        }while (result.isTruncated());

    }


    public List<String> bucketChild(){

        List<String> stringList = new ArrayList<>();
        try {

            ObsClient obsClient = ObsClientFactory.getObsClient();
            ListObjectsRequest request = new ListObjectsRequest(bucketName);
            request.setMaxKeys(1000);
            request.setDelimiter("/");
            //request.setPrefix(prefix);
            ObjectListing result = null;


            do {
                result = obsClient.listObjects(request);
                List<String> list = result.getCommonPrefixes();
                request.setMarker(result.getNextMarker());
                stringList.addAll(list);

            }while (result.isTruncated());
            return stringList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stringList;
    }

    public Map<String,Object> folderInfo(String prefix){
         Map<String,Object> map = new HashMap<>();
         logger.info("开始计算"+prefix+"文件夹大小");
         long startTime = System.currentTimeMillis();
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        request.setMaxKeys(1000);
        request.setPrefix(prefix);
        // request.setDelimiter("/");
        ObjectListing result = null;
        ObsClient obsClient = ObsClientFactory.getObsClient();
        long size = 0;
        int count = 0;
        do {
            result = obsClient.listObjects(request);
            List<ObsObject> objectsList = result.getObjects();
            for (ObsObject obs : objectsList){
                size += obs.getMetadata().getContentLength();
            }
            request.setMarker(result.getNextMarker());
            count+=objectsList.size();
        }while (result.isTruncated());
        BigDecimal bg = new BigDecimal(size);
        BigDecimal temp = bg.divide(new BigDecimal("1024"),4,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("1024"),4,BigDecimal.ROUND_HALF_UP);
        map.put("size",temp);
        map.put("count",count);
        logger.info("结束计算"+prefix+"文件夹大小");
        return map;
    }

}
